package com.ebspp.client.serverManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransportException;


import com.ebspp.global.General;
import com.ebspp.thrift.DataMsg;
import com.ebspp.thrift.Identity;
import com.ebspp.thrift.ResourceType;

/**
 * It has the whole knowledge of the server information
 * It manages all the potential EBS++ servers
 * It managers all the connection managers
 * 
 * It tells the EBS++ client which server to use for write
 * 
 * Note: all connection open and close should come through this class!
 * @author x23pan
 *
 */
public class ServerManager 
{
	//servers list maintained by the client
	private static List<String> servers = new ArrayList<String>();
	
	private static MsgConnManager msgConnManager;
	private static WriteConnManager wConnManager;
	private static ReadConnManager rConnManager;
	private static GarbageConnManager gbConnManager;

	IStat stat;

	
	static
	{	
		IStat stat = new StatisticsDB();
		servers.add(General.getServerName());

		msgConnManager = new MsgConnManager(stat);
		for(String serverIP : servers)
		{
			msgConnManager.createMsgConn(serverIP);
			msgConnManager.initHeartBeat(serverIP);
		}
		wConnManager = new WriteConnManager(stat);
		rConnManager = new ReadConnManager(stat);
		gbConnManager = new GarbageConnManager();
	}
	
	
	public static List<String> getServers()
	{
		return servers;
	}
	public static int getWConnRes(String server, int bufID)
	{
		return wConnManager.getBufServerRes(server, bufID);
	}
	public static int getRConnRes(String server, int bufID)
	{
		return rConnManager.getBufServerRes(server, bufID);
	}
	
	
	//garbage connection related functions
	public static GarbageConnection createGBConn(String server,  ResourceType type, Identity cID)
	{
		return gbConnManager.createGBConn(server, type, cID);
	}
	public static boolean closeGBConn(String server, Identity id)
	{
		return gbConnManager.closeGBConn(server);
	}
	public static List<DataMsg> garbageCollect(List<DataMsg> gbs, String server) throws TException
	{
		return gbConnManager.garbageCollect(gbs, server);
	}
	
	//write connection related functions
	public static WriteConnection getWCandidate(ResourceType type, int bufID, Identity cID)
	{
		//strategy needed here
		String server = servers.get(0);		
		return createWConn(server, type, bufID, cID);
	}
	public static WriteConnection createWConn(String server, ResourceType type, int bufID, Identity cID)
	{
		WriteConnection wConn =  wConnManager.createWConn(server, type, bufID, cID);
		return wConn;
	}
	public static boolean closeWConn(String server, int bufID)
	{
		return wConnManager.closeWConn(bufID, server);
	}
	public static boolean wProvision(String server, int bufID, int amount)
	{
		return wConnManager.provision(server, bufID, amount);
	}
	public static List<DataMsg> write(List<DataMsg> data, String server, int bufID) throws TException
	{
		return wConnManager.write(data, server, bufID);
	}
	
	
	
	//read related functions
	public static ReadConnection createRConn(String server, ResourceType type, int bufID, Identity cID)
	{
		return rConnManager.createRConn(server, type, bufID, cID);
	}
	public static boolean closeRConn(String server, int bufID)
	{
		return rConnManager.closeRConn(bufID, server);
	}
	public static String rProvision(String server, int bufID, int amount)
	{
		return rConnManager.provision(server, bufID, amount);
	}
	public static List<DataMsg> read(List<DataMsg> data, String server, int bufID) throws TException
	{
		return rConnManager.read(data, server, bufID);
	}
	

	//msg heart beat realted functions
	public static boolean watch(String server, ResourceType resType, Identity wID) throws TException
	{
		return msgConnManager.watch(server, resType, wID);
	}
	public static boolean deWatch(String server, ResourceType resType, Identity wID)
	{
		return msgConnManager.deWatch(server, resType, wID);
	}
}
